package com.example.javafx_demo_01.controller;

import de.felixroske.jfxsupport.FXMLController;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Cursor;
import javafx.scene.control.*;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Circle;
import javafx.scene.text.Font;
import javafx.stage.FileChooser;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.util.*;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

@FXMLController
public class PrimaryStageController implements Initializable {
    @FXML
    private Button buttonObject;
    @FXML
    private TextField xTextFieldObject;
    @FXML
    private TextField yTextFieldObject;
    @FXML
    private Button addTextButton;
    @FXML
    private TextField addTextField;
    @FXML
    private Pane mainPane;
    @FXML
    private TextField xLabel;
    @FXML
    private TextField yLabel;
    @FXML
    private Label imgPathObject;
    @FXML
    private Button delTextButton;
    @FXML
    private Circle circleObject;
    @FXML
    private Button getJiaoDian;
    @FXML
    private Button suduAdd;
    @FXML
    private Button suduDel;
    @FXML
    private Label thisSuDuField;
    @FXML
    private TextField suDuinput;
    @FXML
    private ImageView imgObject;
    @FXML
    private Pane imgPane;
    @FXML
    private ScrollBar xScrollBar;
    @FXML
    private ScrollBar yScrollBar;
    @FXML
    private Label fontFieldObject;
    @FXML
    private Label fontSelectFieldObject;
    @FXML
    private Label fontSizeFieldObject;
    @FXML
    private ComboBox<String> fontSelectInputObject;
    @FXML
    private Spinner<Double> fontSizeInputObject;
    @FXML
    private Button printButtonObject;

    private Font font;
    private final Double Text_WIDTH = 20.0;
    private Double sudu = 10.0;

    private  File[] files;

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        File file1 = new File(Objects.requireNonNull(this.getClass().getClassLoader().getResource("font_file")).getFile());
        files = file1.listFiles();
        if (files != null) {
            for (File file : files){
                fontSelectInputObject.getItems().add(file.getName().substring(0,file.getName().lastIndexOf(".")));
            }//字体文件初始化
            fontSelectInputObject.setValue(files[2].getName().substring(0,files[2].getName().lastIndexOf(".")));
            try {
                font = Font.loadFont(new FileInputStream(files[fontSelectInputObject.getSelectionModel().getSelectedIndex()].getPath()),Text_WIDTH);
            } catch (FileNotFoundException e) {//字体和大小初始化
                throw new RuntimeException(e);
            }
        }
        //字体样式选择
        fontSelectInputObject.valueProperty().addListener(e ->{
            try {
                font = Font.loadFont(new FileInputStream(files[fontSelectInputObject.getSelectionModel().getSelectedIndex()].getPath()),fontSizeInputObject.getValue());
                fontZiTiStyle(font,files[fontSelectInputObject.getSelectionModel().getSelectedIndex()],fontSizeInputObject.getValue());
            } catch (FileNotFoundException ex) {
                throw new RuntimeException(ex);
            }
        });
        SpinnerValueFactory<Double> s = new SpinnerValueFactory.DoubleSpinnerValueFactory(0,100.0,Text_WIDTH,1);
        fontSizeInputObject.setValueFactory(s);
        //字体大小
        fontSizeInputObject.valueProperty().addListener(e -> {
            try {
                font = Font.loadFont(new FileInputStream(files[fontSelectInputObject.getSelectionModel().getSelectedIndex()].getPath()),fontSizeInputObject.getValue());
            } catch (FileNotFoundException ex) {
                throw new RuntimeException(ex);
            }
            fontZiTiStyle(font,files[fontSelectInputObject.getSelectionModel().getSelectedIndex()],fontSizeInputObject.getValue());
        });
        mainPane.getStylesheets().add("/css/PrimaryStage.css");
        if (getJiaoDian.isDisable()) {
            suduAdd.setVisible(true);
            suduDel.setVisible(true);
            thisSuDuField.setVisible(true);
            suDuinput.setVisible(true);
            suDuinput.setDisable(true);
        }
        //导入图
        buttonObject.setOnAction((event) -> {
            FileChooser fileChooser = new FileChooser();
            File file = fileChooser.showOpenDialog(null);
            if (file == null) return;
            Image image = new Image(file.getPath());
            xTextFieldObject.setText(String.valueOf(image.getWidth()));
            yTextFieldObject.setText(String.valueOf(image.getHeight()));
            imgObject.setFitWidth(image.getWidth());
            imgObject.setFitHeight(image.getHeight());
            imgPane.setPrefWidth(imgObject.getFitWidth());
            imgPane.setPrefHeight(imgObject.getFitHeight());
            imgObject.setImage(image);
            imgPathObject.setText(image.getUrl());
        });
        //添加一个文本标签
        addTextButton.setOnAction(event -> {
            try {
                font = Font.loadFont(new FileInputStream(files[2].getPath()),Text_WIDTH);
            } catch (FileNotFoundException e) {
                throw new RuntimeException(e);
            }
            String str = addTextField.getText();
            if(str != null && !"".equals(str)){
                Label label = new Label(str);
                label.setLayoutX(0);
                label.setLayoutY(0);
                label.setPrefWidth(str.length()*Text_WIDTH);
                label.setPrefHeight(15);
                label.setFont(font);
                imgPane.getChildren().add(label);
                addTextField.setText("");
                addLabelScene(label);
            }
        });
        //删除文本标签
        delTextButton.setOnAction(event -> {
            delLabel(imgPane);
            fontCommDisBoolean(true);
        });
        yScrollBar.valueProperty().addListener((e,oldV,newV) -> {
            double su_du = imgObject.getFitHeight() / yScrollBar.getMax();
            imgObject.setLayoutY(-newV.doubleValue() * su_du);
            imgPane.setLayoutY(-newV.doubleValue() * su_du);
            fieldMoveY(-(newV.doubleValue() - oldV.doubleValue())*su_du);
        });
        xScrollBar.valueProperty().addListener((e,oldV,newV) -> {
            double su_du = imgObject.getFitWidth() / yScrollBar.getMax();
            imgObject.setLayoutX(-newV.doubleValue() * su_du);
            imgPane.setLayoutX(-newV.doubleValue() * su_du);
            fieldMoveX(-(newV.doubleValue() - oldV.doubleValue())*su_du);
        });
        //打印图片
        printButtonObject.setOnAction(e -> {
            try {
                printCard(new File(imgObject.getImage().getUrl()));
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
        });
        //获取焦点
        getJiaoDian.setOnAction(e -> {
            suduAdd.setDisable(false);
            suduDel.setDisable(false);
            suduAdd.setVisible(true);
            suduDel.setVisible(true);
            thisSuDuField.setVisible(true);
            suDuinput.setVisible(true);
            suDuinput.setDisable(false);
            suDuinput.setText(String.valueOf(sudu));
            circleObject.requestFocus();
        });
        suduAdd.setOnAction(e -> {
            sudu++;
            suDuinput.setText(String.valueOf(sudu));
        });
        suduDel.setOnAction(e -> {
            sudu--;
            suDuinput.setText(String.valueOf(sudu));
        });
    }
    private final List<Map<String,Object>> labelList = new LinkedList<>();//储存
    //label.setOnMouseMoved();鼠标在节点内移动事件
    //label.setOnMouseEntered();鼠标进入组件节点时事件
    //setOnMousePressed单击没有释放
    //setOnMouseReleased双击
    // 鼠标点击没有释放事件
    /**
     * label添加事件
     */
    private void addLabelScene(Label label){
        label.setOnMouseClicked(e -> {
            labelCanvas(label);
            fontCommDisBoolean(false);
            changeFontComm(fontSelectInputObject,fontSizeInputObject);
        });
        Map<String,Object> labelMap = new HashMap<>();
        labelMap.put("is",false);
        labelMap.put("label",label);
        labelMap.put("font_style",files[2]);
        labelMap.put("font_size",Text_WIDTH);
        labelList.add(labelMap);
    }
    /**
     * label点击事件场景设置
     * @param label label
     */
    private void labelCanvas(Label label){
        AtomicReference<Double> x = new AtomicReference<>((double) 0);
        AtomicReference<Double> y = new AtomicReference<>((double) 0);
        for (Map<String,Object> map : labelList) {
            boolean is = (boolean) map.get("is");
            Label label1 = (Label) map.get("label");
            if (label1.equals(label)){
                if (is){
                    continue;
                }
                label1.getStyleClass().add("nihao");
                xLabel.setText(String.valueOf(label1.getLayoutX()));
                yLabel.setText(String.valueOf(label1.getLayoutY()));
                label1.setOnMousePressed(eee -> {
                    x.set(eee.getSceneX() - label1.getLayoutX());
                    y.set(eee.getSceneY() - label1.getLayoutY());
                });
                //鼠标拖拽组件事件
                label1.setOnMouseDragged(er->{
                    label1.setLayoutX(er.getSceneX() - x.get());
                    label1.setLayoutY(er.getSceneY() - y.get());
                    xLabel.setText(String.valueOf(label1.getLayoutX()));
                    yLabel.setText(String.valueOf(label1.getLayoutY()));
                });
                label1.setCursor(Cursor.MOVE);
                map.put("is",true);
            }else{
                label1.getStyleClass().remove("nihao");
                label1.setCursor(Cursor.DEFAULT);
                label1.setOnMouseDragged(e -> {});
                label1.setOnMousePressed(eee -> {});
                map.put("is",false);
            }
        }
    }
    /**
     * 删除文本标签
     */
    private void delLabel(Pane pane){
        for (Map<String,Object> map : labelList) {
            boolean is = (boolean) map.get("is");
            Label label1 = (Label) map.get("label");
            if (is){
                pane.getChildren().remove(label1);
                labelList.remove(map);
                return;
            }
        }
    }

    /**
     * x轴移动
     * @param keyCode 键盘code
     * @param oldX 移动组件当前x坐标位置
     * @param parentW 移动画布宽
     * @param su_du 速度
     * @return 移动后的位置
     */
    private double moveX(int keyCode,double oldX,double parentW,double su_du){
        double x;
        switch (keyCode){
            case 68://右
                x = oldX + su_du;
                if (x > parentW){
                    x = parentW;
                }
                return x;
            case 65://左
                x = oldX - su_du;
                if (x < 0){
                    x = 0;
                }
                return x;
            default:
                return oldX;
        }
    }
    /**
     * y轴移动
     * @param keyCode 键盘code
     * @param oldY 移动组件当前y坐标位置
     * @param parentH 移动画布高
     * @param su_du 速度
     * @return 移动后的位置
     */
    private double moveY(int keyCode,double oldY,double parentH,double su_du){
        double y;
        switch (keyCode){
            case 87://上
                y = oldY - su_du;
                if (y < 0){
                    y = 0;
                }
                return y;
            case 83://下
                y = oldY + su_du;
                if (y > parentH){
                    y = parentH;
                }
                return y;
            default:
                return oldY;
        }
    }

    /**
     * 字体样式修改
     * @param bool false关闭/true开启
     */
    private void fontCommDisBoolean(boolean bool){
        fontFieldObject.setDisable(bool);
        fontSelectFieldObject.setDisable(bool);
        fontSizeFieldObject.setDisable(bool);
        fontSelectInputObject.setDisable(bool);
        fontSizeInputObject.setDisable(bool);
        if (bool){
            fontSelectInputObject.setValue(files[2].getName().substring(0,files[2].getName().lastIndexOf(".")));
            fontSizeInputObject.getValueFactory().setValue(Text_WIDTH);
        }
    }

    /**
     * 修改字体
     * @param font 字体样式
     * @param file 字体文件
     * @param size 字体大小
     */
    private void fontZiTiStyle(Font font,File file,Double size){
        for (Map<String,Object> map : labelList) {
            boolean is = (boolean) map.get("is");
            Label label1 = (Label) map.get("label");
            if (is){
                label1.setFont(font);
                label1.setPrefWidth(label1.getText().length()*fontSizeInputObject.getValue());
                map.put("font_style",file);
                map.put("font_size",size);
                return;
            }
        }
    }

    /**
     * 点击控件时场景数据修改
     * @param comboBox 显示控件修改
     * @param spinner 显示控件修改
     */
    private void changeFontComm(ComboBox<String> comboBox,Spinner<Double> spinner){
        for (Map<String,Object> map : labelList) {
            boolean is = (boolean) map.get("is");
            File file = (File) map.get("font_style");
            double size = (Double) map.get("font_size");
            if (is){
                spinner.getValueFactory().setValue(size);
                comboBox.setValue(file.getName().substring(0,file.getName().lastIndexOf(".")));
                return;
            }
        }
    }

    /**
     *  label y移动
     * @param y 移动值
     */
    private void fieldMoveY(double y){
        for (Map<String,Object> map : labelList) {
            Label label = (Label) map.get("label");
            label.setLayoutY(label.getLayoutY() + y);
        }
    }

    /**
     * label x移动
     * @param x 移动值
     */
    private void fieldMoveX(double x){
        for (Map<String,Object> map : labelList) {
            Label label = (Label) map.get("label");
            label.setLayoutX(label.getLayoutX() + x);
        }
    }

    private float hei = 35;
    private float wid = 20;
    private int fs = 5;
    private void printCard(File file) throws IOException {//打印证书
        BufferedImage image = ImageIO.read(file);//将图片读取到缓存类
        Graphics2D graphics = image.createGraphics();
        graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);// 消除文字锯齿
        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);// 消除图片锯齿
        for (Map<String,Object> map : labelList) {
            Label label = (Label) map.get("label");
            graphics.setFont(new java.awt.Font("仿宋", java.awt.Font.PLAIN, (int) label.getFont().getSize()));
            graphics.setColor(Color.BLACK);
            graphics.drawString(label.getText(),(float) (label.getLayoutX()-imgObject.getLayoutX()),(float) (label.getLayoutY() - imgObject.getLayoutY())+ hei);
        }
        ImageIO.write(image,"png",new File("C:\\Users\\ASUS\\Desktop\\img\\card_image\\"+file.getName().substring(0,file.getName().lastIndexOf("."))+".png"));
        graphics.dispose();
    }
}
